package com.example.myweb.Service.Auth.Impl;

import com.example.myweb.Domain.Entity.Follow;
import com.example.myweb.Domain.Entity.User;
import com.example.myweb.Dto.FollowUserInfoDTO;
import com.example.myweb.Exception.CustomException;

import com.example.myweb.Repository.JpaRepository.FollowRepository;
import com.example.myweb.Repository.JpaRepository.UserRepository;
import com.example.myweb.Service.Auth.FollowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class FollowServiceImpl implements FollowService {

    @Autowired
    private FollowRepository followRepository;
    @Autowired
    private UserRepository userRepository;

    @Override
    public void followUser(User currentUser, Long followedUserId) {
        if (currentUser.getUserId().equals(followedUserId)) {
            throw new CustomException("不能关注自己", HttpStatus.BAD_REQUEST);
        }

        User followedUser = userRepository.findById(followedUserId)
                .orElseThrow(() -> new CustomException("要关注的用户不存在", HttpStatus.NOT_FOUND));

        // 检查是否已经关注过（虽然数据库有唯一约束，但在代码层面检查可以提供更友好的提示）
        if (followRepository.findByFollowerAndFollowed(currentUser, followedUser).isPresent()) {
            // 如果已经关注，可以直接静默返回成功，实现幂等性
            return;
        }

        Follow follow = new Follow();
        follow.setFollower(currentUser);
        follow.setFollowed(followedUser);

        try {
            followRepository.save(follow);
        } catch (DataIntegrityViolationException e) {
            // 这是捕获并发情况下数据库唯一约束冲突的异常
            // 同样静默处理，因为最终状态是“已关注”，符合预期
        }
    }

    @Override
    @Transactional // 使用事务确保操作原子性
    public void unfollowUser(User currentUser, Long followedUserId) {
        // 调用JPA的deleteBy...方法，它会先查询再删除，是事务性的
        long deletedCount = followRepository.deleteByFollowerAndFollowed_UserId(currentUser, followedUserId);

        // 可以选择性地检查是否真的删除了记录
        if (deletedCount == 0) {
            // 如果你想在用户尝试取关一个未关注的人时给出提示，可以抛出异常
             throw new CustomException("你尚未关注该用户", HttpStatus.BAD_REQUEST);
            // 但通常静默成功是更好的用户体验，因为最终状态（未关注）是符合用户预期的
        }
    }

    @Override
    public List<Long> getFollowingUserIds(User currentUser) {
        return followRepository.findFollowedUserIdsByFollower(currentUser);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<FollowUserInfoDTO> getFollowingList(User user, Pageable pageable, User currentUser) {
        Page<Follow> followingPage = followRepository.findByFollower(user, pageable);
        return convertFollowPageToDto(followingPage, currentUser, true);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<FollowUserInfoDTO> getFollowerList(User user, Pageable pageable, User currentUser) {
        Page<Follow> followerPage = followRepository.findByFollowed(user, pageable);
        return convertFollowPageToDto(followerPage, currentUser, false);
    }

    // --- 核心辅助方法 ---
    private Page<FollowUserInfoDTO> convertFollowPageToDto(Page<Follow> followPage, User currentUser, boolean isFollowingList) {
        List<User> targetUsers = followPage.getContent().stream()
                .map(follow -> isFollowingList ? follow.getFollowed() : follow.getFollower())
                .collect(Collectors.toList());

        Set<Long> currentUserFollowingIds = new HashSet<>();
        if (currentUser != null && !targetUsers.isEmpty()) {
            List<Long> targetUserIds = targetUsers.stream().map(User::getUserId).collect(Collectors.toList());
            currentUserFollowingIds = followRepository.findFollowedIdsByCurrentUser(currentUser, targetUserIds);
        }

        final Set<Long> finalCurrentUserFollowingIds = currentUserFollowingIds;
        return followPage.map(follow -> {
            User targetUser = isFollowingList ? follow.getFollowed() : follow.getFollower();
            FollowUserInfoDTO dto = new FollowUserInfoDTO();
            dto.setUserId(targetUser.getUserId());
            dto.setNickname(targetUser.getNickname());
            dto.setAvatarUrl(targetUser.getAvatarUrl());
            dto.setBio(targetUser.getBio());
            // 检查当前登录用户是否也关注了这个人
            dto.setFollowing(finalCurrentUserFollowingIds.contains(targetUser.getUserId()));
            return dto;
        });
    }
}